package com.peas.platform.module.icims.base.approve.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.peas.platform.common.core.enums.BaseEnum;
import com.peas.platform.framework.mybatisplus.domain.BaseDomain;
import com.peas.platform.framework.mybatisplus.po.BasePo;
import com.peas.platform.framework.mybatisplus.service.BaseServiceImpl;
import com.peas.platform.module.icims.base.approve.api.req.SaveApproveVo;
import com.peas.platform.module.icims.base.approve.domain.ApproveDomain;
import com.peas.platform.module.icims.base.approve.dto.ApproveConditionDto;
import com.peas.platform.module.icims.base.approve.dto.ApproveDto;
import com.peas.platform.module.icims.base.approve.dto.ApproveNodeDto;
import com.peas.platform.module.icims.base.approve.enums.ApproveBusiness;
import com.peas.platform.module.icims.base.approve.enums.ApproveBusinessField;
import com.peas.platform.module.icims.base.approve.enums.ApproveType;
import com.peas.platform.module.icims.base.approve.service.ApproveConditionService;
import com.peas.platform.module.icims.base.approve.service.ApproveNodeService;
import com.peas.platform.module.icims.base.approve.service.ApproveService;
import com.peas.platform.module.icims.base.sys.enums.CommonEnableDisable;
import com.peas.platform.module.icims.budget.adjust.dto.BudgetNewDto;
import com.peas.platform.module.icims.budget.adjust.service.BudgetNewService;
import com.peas.platform.module.icims.budget.apply.dto.BudgetOneDto;
import com.peas.platform.module.icims.budget.apply.dto.BudgetTwoDto;
import com.peas.platform.module.icims.budget.apply.service.BudgetOneService;
import com.peas.platform.module.icims.budget.apply.service.BudgetTwoService;
import com.peas.platform.module.icims.budget.project.dto.BudgetProjectTwoDto;
import com.peas.platform.module.icims.budget.project.service.BudgetProjectTwoService;
import com.peas.platform.module.icims.contract.initial.dto.ContractInitialDto;
import com.peas.platform.module.icims.contract.initial.service.*;
import com.peas.platform.module.icims.expenditure.basal.dto.ExpenditureFiscalDto;
import com.peas.platform.module.icims.expenditure.basal.service.ExpenditureFiscalService;
import com.peas.platform.module.icims.expenditure.expenses.dto.*;
import com.peas.platform.module.icims.expenditure.expenses.enums.ExpenditureReimbursementFeetype;
import com.peas.platform.module.icims.expenditure.expenses.enums.ExpenditureReimbursementType;
import com.peas.platform.module.icims.expenditure.expenses.service.*;
import com.peas.platform.module.icims.expenditure.kpis.dto.ExpenditureAdjustmentDto;
import com.peas.platform.module.icims.expenditure.kpis.dto.ExpenditureKpiDto;
import com.peas.platform.module.icims.expenditure.kpis.dto.ExpenditureQuotaDto;
import com.peas.platform.module.icims.expenditure.kpis.service.ExpenditureAdjustmentService;
import com.peas.platform.module.icims.expenditure.kpis.service.ExpenditureKpiService;
import com.peas.platform.module.icims.expenditure.kpis.service.ExpenditureQuotaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ApproveServiceImpl extends BaseServiceImpl<ApproveDto> implements ApproveService {

    @Resource
    private ApproveDomain approveDomain;
    @Resource
    private ApproveNodeService approveNodeService;
    @Resource
    private ApproveConditionService approveConditionService;
    @Resource
    private BudgetProjectTwoService budgetProjectTwoService;
    @Resource
    private BudgetOneService budgetOneService;
    @Resource
    private BudgetTwoService budgetTwoService;
    @Resource
    private BudgetNewService budgetNewService;
    @Resource
    private ExpenditureKpiService expenditureKpiService;
    @Resource
    private ExpenditureQuotaService expenditureQuotaService;
    @Resource
    private ExpenditureAdjustmentService expenditureAdjustmentService;
    @Resource
    private ExpenditureApplicationService expenditureApplicationService;
    @Resource
    private ExpenditureReimbursementService expenditureReimbursementService;
    @Resource
    private ContractInitialService contractInitialService;
    @Resource
    private ContractInitialSupplementalService contractInitialSupplementalService;
    @Resource
    private ContractInitialChangeService contractInitialChangeService;
    @Resource
    private ContractInitialCashService contractInitialCashService;
    @Resource
    private ContractInitialBorrowService contractInitialBorrowService;
    @Resource
    private ContractInitialCheckingService contractInitialCheckingService;
    @Resource
    private ContractInitialInterruptService contractInitialInterruptService;
    @Resource
    private ContractInitialTerminateService contractInitialTerminateService;
    @Resource
    private ExpenditureFiscalService expenditureFiscalService;
    @Resource
    private ExpenditureReimbursementTravelService expenditureReimbursementTravelService;
    @Resource
    private ExpenditureReimbursementContractService expenditureReimbursementContractService;
    @Resource
    private ExpenditureReimbursementMeetingService expenditureReimbursementMeetingService;
    @Resource
    private ExpenditureReimbursementTrainingService expenditureReimbursementTrainingService;
    @Resource
    private ExpenditureReimbursementTrafficService expenditureReimbursementTrafficService;
    @Resource
    private ExpenditureReimbursementAbroadService expenditureReimbursementAbroadService;
    @Resource
    private ExpenditureReimbursementOtherService expenditureReimbursementOtherService;

    @Override
    public BaseDomain<ApproveDto, ? extends BasePo> getDomain() {
        return approveDomain;
    }

    @Transactional
    @Override
    public void saveApprove(SaveApproveVo vo) {
        ApproveDto ad = BeanUtil.copyProperties(vo, ApproveDto.class);
        int result = ad.getId() == null ? this.save(ad) : this.updateById(ad);
        Assert.isTrue(result > 0, "保存失败");
        // nodes
        List<ApproveNodeDto> ands = approveNodeService.listByApproveId(ad.getId());
        approveNodeService.removeBatchByList(ands);
        Assert.notEmpty(vo.getNodes(), "请录入审批节点");
        List<ApproveNodeDto> andList = new ArrayList<>();
        vo.getNodes().forEach(v -> {
            ApproveNodeDto dto = BeanUtil.copyProperties(v, ApproveNodeDto.class);
            dto.setApproveId(ad.getId());
            andList.add(dto);
        });
        approveNodeService.saveBatch(andList);
        // conditions
        List<ApproveConditionDto> acds = approveConditionService.listByField("approveId", ad.getId());
        approveConditionService.removeBatchByList(acds);
        if (StrUtil.equals(vo.getApproveType(), ApproveType.conditional.getKey())) {
            Assert.notEmpty(vo.getConditions(), "请录入审批模版条件");
            List<ApproveConditionDto> acdList = new ArrayList<>();
            vo.getConditions().forEach(v -> {
                ApproveConditionDto dto = BeanUtil.copyProperties(v, ApproveConditionDto.class);
                dto.setApproveId(ad.getId());
                acdList.add(dto);
            });
            approveConditionService.saveBatch(acdList);
        }
        // 检查
        approveNodeService.checkApproveNode(ad.getId());
    }

    private List<ApproveDto> queryApproveByBusinessByExpenditureKpi(ApproveBusiness ab, ExpenditureKpiDto dto) {
        List<ApproveDto> result = new CopyOnWriteArrayList<>();
        Map<ApproveDto, List<ApproveConditionDto>> map = approveConditionService.queryApproveConditionByBusiness(ab);
        map.forEach((ad, acds) -> {
            final AtomicBoolean match = new AtomicBoolean(true);
            acds.forEach(acd -> {
                ApproveBusinessField abf = BaseEnum.key2Enum(ApproveBusinessField.class, acd.getApproveConditionField());
                List<String> values = StrUtil.split(acd.getApproveConditionValues(), ",").stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                log.warn("----------------------------queryApproveByBusinessByExpenditureKpi");
                log.warn("abf:" + abf);
                log.warn("values:" + values);
                if (CollUtil.isNotEmpty(values)) {
                    switch (abf) {
                        case expenditureKpi001:
                            String fundType = dto.getFundType();
                            if (match.get() && !values.contains(fundType)) {
                                match.set(false);
                            }
                            break;
                        case expenditureKpi002:
                            String expenditureFiscalIdStr = dto.getExpenditureFiscalId();
                            Long expenditureFiscalId = Long.valueOf(CollUtil.getLast(StrUtil.split(expenditureFiscalIdStr, ",")));
                            ExpenditureFiscalDto efd = expenditureFiscalService.getById(expenditureFiscalId);
                            if (match.get() && !values.contains(efd.getType())) {
                                match.set(false);
                            }
                            break;
                        case expenditureKpi003:
                            BigDecimal amount = dto.getAmount();
                            BigDecimal min = new BigDecimal(values.get(0));
                            BigDecimal max = values.size() > 1 ? new BigDecimal(values.get(1)) : BigDecimal.valueOf(Integer.MAX_VALUE);
                            if (match.get() && (amount.compareTo(min) < 0 || amount.compareTo(max) > 0)) {
                                match.set(false);
                            }
                            break;
                    }
                    log.warn("----------------------------queryApproveByBusinessByExpenditureKpi,match:" + match.get());
                } else {
                    log.warn("values is empty, match:" + match.get());
                }
            });
            if (match.get()) {
                result.add(ad);
            }
        });
        return result;
    }

    private List<ApproveDto> queryApproveByBusinessByExpenditureQuota(ApproveBusiness ab, ExpenditureQuotaDto dto) {
        List<ApproveDto> result = new CopyOnWriteArrayList<>();
        Map<ApproveDto, List<ApproveConditionDto>> map = approveConditionService.queryApproveConditionByBusiness(ab);
        map.forEach((ad, acds) -> {
            final AtomicBoolean match = new AtomicBoolean(true);
            acds.forEach(acd -> {
                ApproveBusinessField abf = BaseEnum.key2Enum(ApproveBusinessField.class, acd.getApproveConditionField());
                List<String> values = StrUtil.split(acd.getApproveConditionValues(), ",").stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                ExpenditureKpiDto kpi = expenditureKpiService.getById(dto.getExpenditureKpiId());
                log.warn("----------------------------queryApproveByBusinessByExpenditureQuota");
                log.warn("abf:" + abf);
                log.warn("values:" + values);
                if (CollUtil.isNotEmpty(values)) {
                    switch (abf) {
                        case expenditureQuota001:
                            String fundType = kpi.getFundType();
                            if (match.get() && !values.contains(fundType)) {
                                match.set(false);
                            }
                            break;
                        case expenditureQuota002:
                            String expenditureFiscalIdStr = dto.getExpenditureFiscalId();
                            Long expenditureFiscalId = Long.valueOf(CollUtil.getLast(StrUtil.split(expenditureFiscalIdStr, ",")));
                            ExpenditureFiscalDto efd = expenditureFiscalService.getById(expenditureFiscalId);
                            if (match.get() && !values.contains(efd.getType())) {
                                match.set(false);
                            }
                            break;
                        case expenditureQuota003:
                            BigDecimal amount = dto.getAmount();
                            BigDecimal min = new BigDecimal(values.get(0));
                            BigDecimal max = values.size() > 1 ? new BigDecimal(values.get(1)) : BigDecimal.valueOf(Integer.MAX_VALUE);
                            if (match.get() && (amount.compareTo(min) < 0 || amount.compareTo(max) > 0)) {
                                match.set(false);
                            }
                            break;
                    }
                    log.warn("----------------------------queryApproveByBusinessByExpenditureQuota,match:" + match.get());
                } else {
                    log.warn("values is empty, match:" + match.get());
                }
            });
            if (match.get()) {
                result.add(ad);
            }
        });
        return result;
    }

    private List<ApproveDto> queryApproveByBusinessByExpenditureAdjustment(ApproveBusiness ab, ExpenditureAdjustmentDto dto) {
        List<ApproveDto> result = new CopyOnWriteArrayList<>();
        Map<ApproveDto, List<ApproveConditionDto>> map = approveConditionService.queryApproveConditionByBusiness(ab);
        map.forEach((ad, acds) -> {
            final AtomicBoolean match = new AtomicBoolean(true);
            acds.forEach(acd -> {
                ApproveBusinessField abf = BaseEnum.key2Enum(ApproveBusinessField.class, acd.getApproveConditionField());
                List<String> values = StrUtil.split(acd.getApproveConditionValues(), ",").stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                ExpenditureKpiDto kpi = expenditureKpiService.getById(dto.getExpenditureKpiId());
                log.warn("----------------------------queryApproveByBusinessByExpenditureAdjustment");
                log.warn("abf:" + abf);
                log.warn("values:" + values);
                if (CollUtil.isNotEmpty(values)) {
                    switch (abf) {
                        case expenditureAdjustment001:
                            String fundType = kpi.getFundType();
                            if (match.get() && !values.contains(fundType)) {
                                match.set(false);
                            }
                            break;
                        case expenditureAdjustment002:
                            String expenditureFiscalIdStr = kpi.getExpenditureFiscalId();
                            Long expenditureFiscalId = Long.valueOf(CollUtil.getLast(StrUtil.split(expenditureFiscalIdStr, ",")));
                            ExpenditureFiscalDto efd = expenditureFiscalService.getById(expenditureFiscalId);
                            if (match.get() && !values.contains(efd.getType())) {
                                match.set(false);
                            }
                            break;
                        case expenditureAdjustment003:
                            BigDecimal amount = dto.getAdjustAmount();
                            BigDecimal min = new BigDecimal(values.get(0));
                            BigDecimal max = values.size() > 1 ? new BigDecimal(values.get(1)) : BigDecimal.valueOf(Integer.MAX_VALUE);
                            if (match.get() && (amount.compareTo(min) < 0 || amount.compareTo(max) > 0)) {
                                match.set(false);
                            }
                            break;
                    }
                    log.warn("----------------------------queryApproveByBusinessByExpenditureAdjustment,match:" + match.get());
                } else {
                    log.warn("values is empty, match:" + match.get());
                }
            });
            if (match.get()) {
                result.add(ad);
            }
        });
        return result;
    }

    private List<ApproveDto> queryApproveByBusinessByExpenditureApplication(ApproveBusiness ab, ExpenditureApplicationDto dto) {
        List<ApproveDto> result = new CopyOnWriteArrayList<>();
        Map<ApproveDto, List<ApproveConditionDto>> map = approveConditionService.queryApproveConditionByBusiness(ab);
        map.forEach((ad, acds) -> {
            final AtomicBoolean match = new AtomicBoolean(true);
            acds.forEach(acd -> {
                ApproveBusinessField abf = BaseEnum.key2Enum(ApproveBusinessField.class, acd.getApproveConditionField());
                List<String> values = StrUtil.split(acd.getApproveConditionValues(), ",").stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                ExpenditureKpiDto kpi = expenditureKpiService.getById(dto.getExpenditureKpiId());
                log.warn("----------------------------queryApproveByBusinessByExpenditureApplication");
                log.warn("abf:" + abf);
                log.warn("values:" + values);
                if (CollUtil.isNotEmpty(values)) {
                    switch (abf) {
                        case expenditureApplication001:
                            String fundType = kpi.getFundType();
                            if (match.get() && !values.contains(fundType)) {
                                match.set(false);
                            }
                            break;
                        case expenditureApplication002:
                            String expenditureFiscalIdStr = kpi.getExpenditureFiscalId();
                            Long expenditureFiscalId = Long.valueOf(CollUtil.getLast(StrUtil.split(expenditureFiscalIdStr, ",")));
                            ExpenditureFiscalDto efd = expenditureFiscalService.getById(expenditureFiscalId);
                            if (match.get() && !values.contains(efd.getType())) {
                                match.set(false);
                            }
                            break;
                        case expenditureApplication003:
                            BigDecimal amount = dto.getAmount();
                            BigDecimal min = new BigDecimal(values.get(0));
                            BigDecimal max = values.size() > 1 ? new BigDecimal(values.get(1)) : BigDecimal.valueOf(Integer.MAX_VALUE);
                            if (match.get() && (amount.compareTo(min) < 0 || amount.compareTo(max) > 0)) {
                                match.set(false);
                            }
                            break;
                    }
                    log.warn("----------------------------queryApproveByBusinessByExpenditureApplication,match:" + match.get());
                } else {
                    log.warn("values is empty, match:" + match.get());
                }
            });
            if (match.get()) {
                result.add(ad);
            }
        });
        return result;
    }

    private List<ApproveDto> queryApproveByBusinessByExpenditureReimbursement(ApproveBusiness ab, ExpenditureReimbursementDto dto) {
        List<ApproveDto> result = new CopyOnWriteArrayList<>();
        Map<ApproveDto, List<ApproveConditionDto>> map = approveConditionService.queryApproveConditionByBusiness(ab);
        ExpenditureKpiDto kpi = expenditureKpiService.getById(dto.getExpenditureKpiId());
        Assert.equals(ExpenditureReimbursementType.normal.getKey(), dto.getReimbursementType(), "数据错误");
        map.forEach((ad, acds) -> {
            final AtomicBoolean match = new AtomicBoolean(true);
            acds.forEach(acd -> {
                ApproveBusinessField abf = BaseEnum.key2Enum(ApproveBusinessField.class, acd.getApproveConditionField());
                List<String> values = StrUtil.split(acd.getApproveConditionValues(), ",").stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                log.warn("----------------------------queryApproveByBusinessByExpenditureReimbursement");
                log.warn("abf:" + abf);
                log.warn("values:" + values);
                if (CollUtil.isNotEmpty(values)) {
                    switch (abf) {
                        case expenditureReimbursement001:
                            String fundType = kpi.getFundType();
                            if (match.get() && !values.contains(fundType)) {
                                match.set(false);
                            }
                            break;
                        case expenditureReimbursement002:
                            String expenditureFiscalIdStr = kpi.getExpenditureFiscalId();
                            Long expenditureFiscalId = Long.valueOf(CollUtil.getLast(StrUtil.split(expenditureFiscalIdStr, ",")));
                            ExpenditureFiscalDto efd = expenditureFiscalService.getById(expenditureFiscalId);
                            if (match.get() && !values.contains(efd.getType())) {
                                match.set(false);
                            }
                            break;
                        case expenditureReimbursement003:
                            BigDecimal amount = dto.getAmount();
                            BigDecimal min = new BigDecimal(values.get(0));
                            BigDecimal max = values.size() > 1 ? new BigDecimal(values.get(1)) : BigDecimal.valueOf(Integer.MAX_VALUE);
                            if (match.get() && amount.compareTo(min) < 0 || amount.compareTo(max) > 0) {
                                match.set(false);
                            }
                            break;
                        case expenditureReimbursement004:
                            values.forEach(v -> {
                                if (StrUtil.isBlank(v)) {
                                    return;
                                }
                                ExpenditureReimbursementFeetype feetype = BaseEnum.key2Enum(ExpenditureReimbursementFeetype.class, v);
                                Assert.notNull(feetype, "费用类型取值不正确");
                                switch (feetype) {
                                    case travel: {
                                        ExpenditureReimbursementTravelDto c = new ExpenditureReimbursementTravelDto();
                                        c.setExpenditureReimbursementId(dto.getId());
                                        long count = expenditureReimbursementTravelService.count(c);
                                        if (match.get() && count <= 0) {
                                            match.set(false);
                                        }
                                        break;
                                    }
                                    case contract: {
                                        ExpenditureReimbursementContractDto c = new ExpenditureReimbursementContractDto();
                                        c.setExpenditureReimbursementId(dto.getId());
                                        long count = expenditureReimbursementContractService.count(c);
                                        if (match.get() && count <= 0) {
                                            match.set(false);
                                        }
                                        break;
                                    }
                                    case meeting:{
                                        ExpenditureReimbursementMeetingDto c = new ExpenditureReimbursementMeetingDto();
                                        c.setExpenditureReimbursementId(dto.getId());
                                        long count = expenditureReimbursementMeetingService.count(c);
                                        if (match.get() && count <= 0) {
                                            match.set(false);
                                        }
                                        break;
                                    }
                                    case training:{
                                        ExpenditureReimbursementTrainingDto c = new ExpenditureReimbursementTrainingDto();
                                        c.setExpenditureReimbursementId(dto.getId());
                                        long count = expenditureReimbursementTrainingService.count(c);
                                        if (match.get() && count <= 0) {
                                            match.set(false);
                                        }
                                        break;
                                    }
                                    case traffic:{
                                        ExpenditureReimbursementTrafficDto c = new ExpenditureReimbursementTrafficDto();
                                        c.setExpenditureReimbursementId(dto.getId());
                                        long count = expenditureReimbursementTrafficService.count(c);
                                        if (match.get() && count <= 0) {
                                            match.set(false);
                                        }
                                        break;
                                    }
                                    case abroad:{
                                        ExpenditureReimbursementAbroadDto c = new ExpenditureReimbursementAbroadDto();
                                        c.setExpenditureReimbursementId(dto.getId());
                                        long count = expenditureReimbursementAbroadService.count(c);
                                        if (match.get() && count <= 0) {
                                            match.set(false);
                                        }
                                        break;
                                    }
                                    case other:{
                                        ExpenditureReimbursementOtherDto c = new ExpenditureReimbursementOtherDto();
                                        c.setExpenditureReimbursementId(dto.getId());
                                        long count = expenditureReimbursementOtherService.count(c);
                                        if (match.get() && count <= 0) {
                                            match.set(false);
                                        }
                                        break;
                                    }
                                }
                            });
                            break;
                    }
                    log.warn("----------------------------queryApproveByBusinessByExpenditureReimbursement,match:" + match.get());
                } else {
                    log.warn("values is empty, match:" + match.get());
                }
            });
            if (match.get()) {
                result.add(ad);
            }
        });
        return result;
    }

    private List<ApproveDto> queryApproveByBusinessByExpenditureReimbursementOther(ApproveBusiness ab, ExpenditureReimbursementDto dto) {
        List<ApproveDto> result = new CopyOnWriteArrayList<>();
        Map<ApproveDto, List<ApproveConditionDto>> map = approveConditionService.queryApproveConditionByBusiness(ab);
        ExpenditureKpiDto kpi = expenditureKpiService.getById(dto.getExpenditureKpiId());
        Assert.equals(ExpenditureReimbursementType.other.getKey(), dto.getReimbursementType(), "数据错误");
        map.forEach((ad, acds) -> {
            final AtomicBoolean match = new AtomicBoolean(true);
            acds.forEach(acd -> {
                ApproveBusinessField abf = BaseEnum.key2Enum(ApproveBusinessField.class, acd.getApproveConditionField());
                List<String> values = StrUtil.split(acd.getApproveConditionValues(), ",").stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                log.warn("----------------------------queryApproveByBusinessByExpenditureReimbursementOther");
                log.warn("abf:" + abf);
                log.warn("values:" + values);
                if (CollUtil.isNotEmpty(values)) {
                    switch (abf) {
                        case expenditureReimbursementOther001:
                            String fundType = kpi.getFundType();
                            if (match.get() && !values.contains(fundType)) {
                                match.set(false);
                            }
                            break;
                        case expenditureReimbursementOther002:
                            String expenditureFiscalIdStr = kpi.getExpenditureFiscalId();
                            Long expenditureFiscalId = Long.valueOf(CollUtil.getLast(StrUtil.split(expenditureFiscalIdStr, ",")));
                            ExpenditureFiscalDto efd = expenditureFiscalService.getById(expenditureFiscalId);
                            if (match.get() && !values.contains(efd.getType())) {
                                match.set(false);
                            }
                            break;
                        case expenditureReimbursementOther003:
                            BigDecimal amount = dto.getAmount();
                            BigDecimal min = new BigDecimal(values.get(0));
                            BigDecimal max = values.size() > 1 ? new BigDecimal(values.get(1)) : BigDecimal.valueOf(Integer.MAX_VALUE);
                            if (match.get() && (amount.compareTo(min) < 0 || amount.compareTo(max) > 0)) {
                                match.set(false);
                            }
                            break;
                    }
                    log.warn("----------------------------queryApproveByBusinessByExpenditureReimbursementOther,match:" + match.get());
                } else {
                    log.warn("values is empty, match:" + match.get());
                }
            });
            if (match.get()) {
                result.add(ad);
            }
        });
        return result;
    }

    @Override
    public List<ApproveDto> queryApproveByBusiness(ApproveBusiness ab, Long businessId) {
        List<ApproveDto> result = null;
        switch (ab) {
            case budgetProjectTwo: {
                Assert.notNull(businessId, "业务单ID不能为空");
                BudgetProjectTwoDto dto = budgetProjectTwoService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                break;
            }
            case budgetOne: {
                Assert.notNull(businessId, "业务单ID不能为空");
                BudgetOneDto dto = budgetOneService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                break;
            }
            case budgetTwo: {
                Assert.notNull(businessId, "业务单ID不能为空");
                BudgetTwoDto dto = budgetTwoService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                break;
            }
            case budgetNew: {
                Assert.notNull(businessId, "业务单ID不能为空");
                BudgetNewDto dto = budgetNewService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                break;
            }
            case budgetAdjust: {
                // TODO
                break;
            }
            case expenditureKpi: {
                Assert.notNull(businessId, "业务单ID不能为空");
                ExpenditureKpiDto dto = expenditureKpiService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                result = this.queryApproveByBusinessByExpenditureKpi(ab, dto);
                break;
            }
            case expenditureQuota: {
                Assert.notNull(businessId, "业务单ID不能为空");
                ExpenditureQuotaDto dto = expenditureQuotaService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                result = this.queryApproveByBusinessByExpenditureQuota(ab, dto);
                break;
            }
            case expenditureAdjustment: {
                Assert.notNull(businessId, "业务单ID不能为空");
                ExpenditureAdjustmentDto dto = expenditureAdjustmentService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                result = this.queryApproveByBusinessByExpenditureAdjustment(ab, dto);
                break;
            }
            case expenditureApplication: {
                Assert.notNull(businessId, "业务单ID不能为空");
                ExpenditureApplicationDto dto = expenditureApplicationService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                result = this.queryApproveByBusinessByExpenditureApplication(ab, dto);
                break;
            }
            case expenditureReimbursement: {
                Assert.notNull(businessId, "业务单ID不能为空");
                ExpenditureReimbursementDto dto = expenditureReimbursementService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                Assert.equals(ExpenditureReimbursementType.normal.getKey(), dto.getReimbursementType(), "报账单类型错误");
                result = this.queryApproveByBusinessByExpenditureReimbursement(ab, dto);
                break;
            }
            case expenditureReimbursementOther: {
                Assert.notNull(businessId, "业务单ID不能为空");
                ExpenditureReimbursementDto dto = expenditureReimbursementService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                Assert.equals(ExpenditureReimbursementType.other.getKey(), dto.getReimbursementType(), "报账单类型错误");
                result = this.queryApproveByBusinessByExpenditureReimbursementOther(ab, dto);
                break;
            }
            case contractInitial: {
                Assert.notNull(businessId, "业务单ID不能为空");
                ContractInitialDto dto = contractInitialService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                Assert.equals("1", dto.getKind(), "合同数据不匹配");
                break;
            }
            case contractMain: {
                Assert.notNull(businessId, "业务单ID不能为空");
                ContractInitialDto dto = contractInitialService.getById(businessId);
                Assert.notNull(dto, "找不到单据");
                Assert.equals("2", dto.getKind(), "合同数据不匹配");
                break;
            }
            case contractSupplemental: {
//                ContractInitialSupplementalDto dto = contractInitialSupplementalService.getById(businessId);
//                Assert.notNull(dto, "找不到单据");
                log.info("合同补充协议直接取通用模版");
                break;
            }
            case contractChange: {
//                ContractInitialChangeDto dto = contractInitialChangeService.getById(businessId);
//                Assert.notNull(dto, "找不到单据");
                log.info("合同变更直接取通用模版");
                break;
            }
            case contractCash: {
//                ContractInitialCashDto dto = contractInitialCashService.getById(businessId);
//                Assert.notNull(dto, "找不到单据");
                log.info("合同请款直接取通用模版");
                break;
            }
            case contractBorrow: {
//                ContractInitialBorrowDto dto = contractInitialBorrowService.getById(businessId);
//                Assert.notNull(dto, "找不到单据");
                log.info("合同借阅直接取通用模版");
                break;
            }
            case contractChecking: {
//                ContractInitialCheckingDto dto = contractInitialCheckingService.getById(businessId);
//                Assert.notNull(dto, "找不到单据");
                log.info("合同验收直接取通用模版");
                break;
            }
            case contractInterrupt: {
//                ContractInitialInterruptDto dto = contractInitialInterruptService.getById(businessId);
//                Assert.notNull(dto, "找不到单据");
                log.info("合同中止直接取通用模版");
                break;
            }
            case contractTerminate: {
//                ContractInitialTerminateDto dto = contractInitialTerminateService.getById(businessId);
//                Assert.notNull(dto, "找不到单据");
                log.info("合同终止直接取通用模版");
                break;
            }
        }
        if (CollUtil.isNotEmpty(result)) {
            return result.stream().sorted((o1, o2) -> o2.getWeight().compareTo(o1.getWeight())).collect(Collectors.toList());
        }
        // 业务通用
        ApproveDto cc1 = new ApproveDto();
        cc1.setApproveType(ApproveType.business.getKey());
        cc1.setModule(ab.getModule().getKey());
        cc1.setBusiness(ab.getKey());
        cc1.setState(CommonEnableDisable.enabled.getKey());
        result = this.list(cc1);
        if (CollUtil.isNotEmpty(result)) {
            return result.stream().sorted((o1, o2) -> o2.getWeight().compareTo(o1.getWeight())).collect(Collectors.toList());
        }
        // 模块通用
        ApproveDto cc2 = new ApproveDto();
        cc2.setApproveType(ApproveType.module.getKey());
        cc2.setModule(ab.getModule().getKey());
        cc2.setState(CommonEnableDisable.enabled.getKey());
        result = this.list(cc2);
        if (CollUtil.isNotEmpty(result)) {
            return result.stream().sorted((o1, o2) -> o2.getWeight().compareTo(o1.getWeight())).collect(Collectors.toList());
        }
        // 全局
        ApproveDto cc3= new ApproveDto();
        cc3.setApproveType(ApproveType.global.getKey());
        cc3.setState(CommonEnableDisable.enabled.getKey());
        result = this.list(cc3);
        return result.stream().sorted((o1, o2) -> o2.getWeight().compareTo(o1.getWeight())).collect(Collectors.toList());
    }

}
